﻿using SIR.Common.Condition;
using System;
using System.Collections.Generic;

namespace SIR.Web
{
	internal static class NameResolver
	{
		/// <summary>
		/// Resolve the naming constraints to ensure unique names of images and folders within the same folder
		/// </summary>
		/// <param name="type">The type of object being checked</param>
		/// <param name="userId">The user id for which the object belongs</param>
		/// <param name="itemId">The identifier for the object beind checked</param>
		/// <param name="groupId">The grouping identifier which is the parent folder Id</param>
		/// <param name="nameValue">The name value of the item</param>
		/// <returns>The new name for the field</returns>
		internal static string Resolve(Type type, long userId, long itemId, long? groupId, string nameValue)
		{
			// Get the name property from the type
			var nameProperty = type.GetProperty("Name");

			var fieldConditions = new List<IPredicate>();
			// Exclude the object being checked
			fieldConditions.Add(new Predicate("Id", itemId, PredicateOperator.NotEqualTo));
			// Match the user ID
			fieldConditions.Add(new Predicate("UserId", userId, PredicateOperator.EqualTo));
			// Check to see if the name matches exact or by the extension counts
			fieldConditions.Add(new PredicateGroup(new[] {
					new Predicate("Name", nameValue, PredicateOperator.EqualTo),
					new Predicate("Name", "Name2", nameValue + " (%)", PredicateOperator.Like)
				}, false));
			// If a group is specified
			if (groupId.HasValue)
			{
				if (type.Name == "Image") // Match images by FolderId
					fieldConditions.Add(new Predicate("FolderId", groupId.Value, PredicateOperator.EqualTo));
				else if (type.Name == "Folder") // Match folders by ParentFolderId
					fieldConditions.Add(new Predicate("ParentFolderId", groupId.Value, PredicateOperator.EqualTo));
			}
			// Find matches
			var matches = DAL.DataServer.Find(type, new PredicateGroup(fieldConditions, true)).Results;
			// If matches found
			if (matches.Count > 0)
			{
				int highestNumber = 1;
				int parsedValue = 0;
				string name;
				// For each match
				foreach (var match in matches)
				{
					// Get the name
					name = nameProperty.GetValue(match).ToString();
					// Match the name as an exact math or containing Name (Number) format
					if (!string.Equals(name, nameValue, StringComparison.Ordinal) &&
						int.TryParse(name.Substring(nameValue.Length + 2,
						name.IndexOf(')', nameValue.Length + 2) - (nameValue.Length + 2)),
						out parsedValue))
					{
						// Find the highest number
						if (highestNumber < parsedValue)
							highestNumber = parsedValue;
					}
				}
				// Reformat the name with a counter
				return string.Format("{0} ({1})", nameValue, highestNumber + 1);
			}
			// No matches, return the current name
			return nameValue;
		}
	}
}